package com.cdeledu.util.apache.io.image;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;

/**
 * @类描述: 图片相关的操作
 * @创建者: 皇族灬战狼
 * @创建时间: 2017年4月7日 下午5:57:33
 * @版本: V1.0
 * @since: JDK 1.7
 */
public final class OperateImageHelper {
	/** ----------------------------------------------------- Fields start */
	// 图形交换格式
	public static String IMAGE_TYPE_GIF = "gif";
	// 联合照片专家组
	public static String IMAGE_TYPE_JPG = "jpg";
	// 联合照片专家组
	public static String IMAGE_TYPE_JPEG = "jpeg";
	// 英文Bitmap（位图）的简写，它是Windows操作系统中的标准图像文件格式
	public static String IMAGE_TYPE_BMP = "bmp";
	// 可移植网络图形
	public static String IMAGE_TYPE_PNG = "png";
	// Photoshop的专用格式Photoshop
	public static String IMAGE_TYPE_PSD = "psd";

	/** ----------------------------------------------------- Fields end */

	/** ----------------------------------------------- [私有方法] */
	private static Rectangle CalcRotatedSize(Rectangle src, int angel) {
		// if angel is greater than 90 degree, we need to do some conversion
		if (angel >= 90) {
			if (angel / 90 % 2 == 1) {
				int temp = src.height;
				src.height = src.width;
				src.width = temp;
			}
			angel = angel % 90;
		}
		double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
		double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
		double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
		double angel_dalta_width = Math.atan((double) src.height / src.width);
		double angel_dalta_height = Math.atan((double) src.width / src.height);

		int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_width));
		int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_height));
		int des_width = src.width + len_dalta_width * 2;
		int des_height = src.height + len_dalta_height * 2;
		return new java.awt.Rectangle(new Dimension(des_width, des_height));
	}

	/**
	 * 计算text的长度（一个中文算两个字符）
	 * 
	 * @param text
	 * @return
	 */
	private static int getLength(String text) {
		int length = 0;
		for (int i = 0; i < text.length(); i++) {
			if (new String(text.charAt(i) + "").getBytes().length > 1) {
				length += 2;
			} else {
				length += 1;
			}
		}
		return length / 2;
	}

	/** ----------------------------------------------- [私有方法] */

	/**
	 * 图片旋转指定角度
	 * 
	 * @param src
	 *            文件流:源图像地址
	 * @param angel
	 *            旋转度
	 * @return
	 */
	public static BufferedImage Rotate(Image src, int angel) {
		int src_width = src.getWidth(null); // 源图宽度
		int src_height = src.getHeight(null); // 源图高度
		angel = angel > 0 ? angel : (360 + angel);
		Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(src_width, src_height)),
				angel);

		BufferedImage res = null;
		res = new BufferedImage(rect_des.width, rect_des.height, BufferedImage.TYPE_INT_RGB);
		Graphics2D g2 = res.createGraphics();
		g2.setPaint(Color.WHITE);
		g2.fillRect(0, 0, rect_des.width, rect_des.height);
		// transform
		g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);
		g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);

		g2.drawImage(src, null, null);
		return res;
	}

	/***
	 * 剪裁图片
	 * 
	 * @param srcImageFile
	 * @param dest
	 * @param x
	 *            起点横坐标
	 * @param y
	 *            纵坐标
	 * @param w
	 *            长
	 * @param h
	 *            高
	 * @throws IOException
	 * @date 2016-3-30下午12:19:10
	 */
	public static boolean cutImage(InputStream srcImageFile, File dest, int x, int y, int w,
			int h) {
		try {
			BufferedImage src = ImageIO.read(srcImageFile); // 读入文件
			Iterator<ImageReader> iterator = ImageIO.getImageReadersByFormatName("jpg");
			ImageReader reader = (ImageReader) iterator.next();

			// 获取图片流
			ByteArrayOutputStream bs = new ByteArrayOutputStream();
			ImageOutputStream ios = ImageIO.createImageOutputStream(bs);
			ImageIO.write(src, "jpg", ios);
			InputStream in = new ByteArrayInputStream(bs.toByteArray());
			ImageInputStream iis = ImageIO.createImageInputStream(in);
			reader.setInput(iis, true);
			ImageReadParam param = reader.getDefaultReadParam();
			x = (x > 0 ? x : 0);
			y = (y > 0 ? y : 0);
			Rectangle rect = new Rectangle(x, y, w, h);
			param.setSourceRegion(rect);
			BufferedImage bi = reader.read(0, param);
			ImageIO.write(bi, "jpg", dest);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 剪裁图片(x,y,w,h,r)
	 * 
	 * @param srcImageFile
	 *            文件流:源图像地址
	 * @param dest
	 *            新图像
	 * @param x
	 *            目标切片起点x坐标
	 * @param y
	 *            目标切片起点y坐标
	 * @param w
	 *            目标切片宽度
	 * @param h
	 *            目标切片高度
	 * @param r
	 *            目标切片旋转度
	 * @return
	 */
	public static boolean cutAndRotateImage(InputStream srcImageFile, File dest, int x, int y,
			int w, int h, int r) {
		try {
			/*
			 * BufferedImage是Image的一个子类，BufferedImage生成的图片在内存里有一个图像缓冲区，
			 * 利用这个缓冲区我们可以很方便的操作这个图片，通常用来做图片修改操作如大小变换、图片变灰、设置图片透明或不透明等。
			 */
			BufferedImage src = ImageIO.read(srcImageFile); // 读入文件

			// 图片旋转指定角度
			BufferedImage tag = Rotate(src, r);

			// 读取图片文件
			Iterator<ImageReader> iterator = ImageIO.getImageReadersByFormatName("jpg");
			ImageReader reader = (ImageReader) iterator.next();

			// 获取图片流
			ByteArrayOutputStream bs = new ByteArrayOutputStream();
			ImageOutputStream ios = ImageIO.createImageOutputStream(bs);
			ImageIO.write(tag, "jpg", ios);
			InputStream in = new ByteArrayInputStream(bs.toByteArray());
			ImageInputStream iis = ImageIO.createImageInputStream(in);
			reader.setInput(iis, true);
			ImageReadParam param = reader.getDefaultReadParam();
			x = (x > 0 ? x : 0);
			y = (y > 0 ? y : 0);

			// 定义一个矩形
			Rectangle rect = new Rectangle(x, y, w, h);

			// 提供一个 BufferedImage，将其用作解码像素数据的目标。
			param.setSourceRegion(rect);
			BufferedImage bi = reader.read(0, param);

			// 保存新图片
			ImageIO.write(bi, "jpg", dest);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	/***
	 * 按照比例缩放
	 * 
	 * @param srcImageFile
	 * @param result
	 * @param scale
	 *            缩放比例
	 * @param flag
	 *            缩放选择:true 放大; false 缩小;
	 * @return
	 * @date 2016-3-30下午2:39:44
	 */
	public static boolean scale(String srcImageFile, String result, int scale, boolean flag) {
		try {
			File file = new File(srcImageFile);
			BufferedImage src = ImageIO.read(file); // 读入文件
			Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("jpg");
			ImageReader reader = (ImageReader) readers.next();
			ImageInputStream iis = ImageIO.createImageInputStream(file);
			reader.setInput(iis, true);
			int width = reader.getWidth(0); // 得到源图宽
			int height = reader.getHeight(0); // 得到源图长
			if (flag) {// 放大
				width = width * scale;
				height = height * scale;
			} else {// 缩小
				width = width / scale;
				height = height / scale;
			}
			Image image = src.getScaledInstance(width, height, Image.SCALE_DEFAULT);
			BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
			Graphics g = tag.getGraphics();
			g.drawImage(image, 0, 0, null); // 绘制缩小后的图
			g.dispose();
			ImageIO.write(tag, "jpg", new File(result));// 输出到文件流
			return true;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
	}

	/***
	 * 缩放图像，按照长宽缩放
	 * 
	 * @param srcImageFile
	 * @param result
	 * @param height
	 *            变换后的高度
	 * @param width
	 *            变换后的长度
	 * @param bb
	 *            比例不对称时，是否补白，true 补白;false 不补白
	 * @return
	 * @date 2016-3-30下午2:44:37
	 */
	public static boolean scale2(String srcImageFile, String result, int height, int width,
			boolean bb) {
		try {

			double ratio = 0.0; // 缩放比例
			File file = new File(srcImageFile);
			BufferedImage bi = ImageIO.read(file); // 读入文件
			Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("jpg");
			ImageReader reader = (ImageReader) readers.next();
			ImageInputStream iis = ImageIO.createImageInputStream(file);
			reader.setInput(iis, true);
			int width1 = reader.getWidth(0); // 得到源图宽
			int height1 = reader.getHeight(0); // 得到源图长
			@SuppressWarnings("static-access")
			Image itemp = bi.getScaledInstance(width, height, bi.SCALE_SMOOTH);
			// 计算比例
			if ((height1 > height) || (width1 > width)) {
				if (height1 > width1) {
					ratio = (new Integer(height)).doubleValue() / height1;
				} else {
					ratio = (new Integer(width)).doubleValue() / width1;
				}
				AffineTransformOp op = new AffineTransformOp(
						AffineTransform.getScaleInstance(ratio, ratio), null);
				itemp = op.filter(bi, null);
			}
			if (bb) {// 补白
				BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
				Graphics2D g = image.createGraphics();
				g.setColor(Color.white);
				g.fillRect(0, 0, width, height);
				if (width == itemp.getWidth(null)) {
					g.drawImage(itemp, 0, (height - itemp.getHeight(null)) / 2,
							itemp.getWidth(null), itemp.getHeight(null), Color.white, null);
				} else {
					g.drawImage(itemp, (width - itemp.getWidth(null)) / 2, 0, itemp.getWidth(null),
							itemp.getHeight(null), Color.white, null);
				}
				g.dispose();
				itemp = image;
			}
			ImageIO.write((BufferedImage) itemp, "JPEG", new File(result));
			return true;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
	}

	/***
	 * 转换图像格式
	 * 
	 * @param srcImageFile
	 *            原图像地址
	 * @param formatName
	 *            转换类型
	 * @param destImageFile
	 *            转换后的地址
	 * @return
	 * @author roychenyi
	 * @date 2016-3-30下午2:49:15
	 */
	public static boolean convert(String srcImageFile, String formatName, String destImageFile) {
		try {
			File f = new File(srcImageFile);
			f.canRead();
			f.canWrite();
			BufferedImage src = ImageIO.read(f);
			ImageIO.write(src, formatName, new File(destImageFile));
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 彩色转为黑白
	 * 
	 * @param srcImageFile
	 *            源图像地址
	 * @param destImageFile
	 *            目标图像地址
	 */
	public final static void gray(String srcImageFile, String destImageFile) {
		try {
			BufferedImage src = ImageIO.read(new File(srcImageFile));
			ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
			ColorConvertOp op = new ColorConvertOp(cs, null);
			src = op.filter(src, null);
			ImageIO.write(src, "jpg", new File(destImageFile));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 给图片添加图片水印
	 * 
	 * @param pressImg
	 *            水印图片
	 * @param srcImageFile
	 *            源图像地址
	 * @param destImageFile
	 *            目标图像地址
	 * @param x
	 *            修正值。 默认在中间
	 * @param y
	 *            修正值。 默认在中间
	 * @param alpha
	 *            透明度：alpha 必须是范围 [0.0, 1.0] 之内（包含边界值）的一个浮点数字
	 */
	public static boolean pressImage(String pressImg, String srcImageFile, String destImageFile,
			int x, int y, float alpha) {
		try {
			File file = new File(srcImageFile);
			BufferedImage src = ImageIO.read(file); // 读入文件
			Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("jpg");
			ImageReader reader = (ImageReader) readers.next();
			ImageInputStream iis = ImageIO.createImageInputStream(file);
			reader.setInput(iis, true);
			int width = reader.getWidth(0); // 得到源图宽
			int height = reader.getHeight(0); // 得到源图长
			BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
			Graphics2D g = image.createGraphics();
			g.drawImage(src, 0, 0, width, height, null);
			// 水印文件
			Image src_biao = ImageIO.read(new File(pressImg));
			int wideth_biao = src_biao.getWidth(null);
			int height_biao = src_biao.getHeight(null);
			g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
			g.drawImage(src_biao, (width - wideth_biao - x), (height - height_biao - y),
					wideth_biao, height_biao, null);
			// 水印文件结束
			g.dispose();
			ImageIO.write((BufferedImage) image, "jpg", new File(destImageFile));
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 给图片添加文字水印
	 * 
	 * @param pressText
	 *            水印文字
	 * @param srcImageFile
	 *            源图像地址
	 * @param destImageFile
	 *            目标图像地址
	 * @param fontName
	 *            水印的字体名称
	 * @param fontStyle
	 *            水印的字体样式
	 * @param color
	 *            水印的字体颜色
	 * @param fontSize
	 *            水印的字体大小
	 * @param x
	 *            修正值
	 * @param y
	 *            修正值
	 * @param alpha
	 *            透明度：alpha 必须是范围 [0.0, 1.0] 之内（包含边界值）的一个浮点数字
	 */
	public static boolean pressText(String pressText, String srcImageFile, String destImageFile,
			String fontName, int fontStyle, Color color, int fontSize, int x, int y, float alpha) {
		try {
			File file = new File(srcImageFile);
			BufferedImage src = ImageIO.read(file); // 读入文件
			Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("jpg");
			ImageReader reader = (ImageReader) readers.next();
			ImageInputStream iis = ImageIO.createImageInputStream(file);
			reader.setInput(iis, true);
			int width = reader.getWidth(0); // 得到源图宽
			int height = reader.getHeight(0); // 得到源图长
			BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
			Graphics2D g = image.createGraphics();
			g.drawImage(src, 0, 0, width, height, null);
			g.setColor(color);
			g.setFont(new Font(fontName, fontStyle, fontSize));
			g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
			// 在指定坐标绘制水印文字
			g.drawString(pressText, (width - (getLength(pressText) * fontSize)) / 2 + x,
					(height - fontSize) / 2 + y);
			g.dispose();
			ImageIO.write(image, "jpg", new File(destImageFile));// 输出到文件流
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * @方法描述: 全屏截图
	 * @param fileName
	 * @throws Exception
	 */
	public static void captureScreen(String fileName) throws Exception {
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		Rectangle screenRectangle = new Rectangle(screenSize);
		Robot robot = new Robot();
		BufferedImage image = robot.createScreenCapture(screenRectangle);
		ImageIO.write(image, "png", new File(fileName));
	}
}
